﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "UiEditModeManager.h"
#include "IEditMode.h"
#include "IUiEditMode.h"
#include "IUiDocument.h"
#include "UiEventManager.h"

#include "UiEditModeEvent.h"
#include "UiEditModeEventArgs.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace gcmp;

UiEditModeManager::UiEditModeManager() :m_isSyncingUIEditMode(false)
{

}

UiEditModeManager::~UiEditModeManager()
{
}

void UiEditModeManager::ClearUiEditMode(IUiDocument* pUIDoc)
{
    if (!pUIDoc)
    {
        return;
    }
    // 只处理该pUIDoc相关的当前UIEditMode
    for (auto ite = m_opCurrentUIEditModes.begin(); ite != m_opCurrentUIEditModes.end(); /**/)
    {
        if ((*ite) && (*ite)->GetUIDocID() == pUIDoc->GetId())
        {
            (*ite)->OnBeforeExitEditMode();
            ite = m_opCurrentUIEditModes.erase(ite);
        }
        else
        {
            ++ite;
        }
    }
}

bool gcmp::UiEditModeManager::UpdateEditModeUi(IUiDocument* pUIDoc)
{
    if (!pUIDoc)
    {
        return false;
    }
    // 只处理该pUIDoc相关的当前UIEditMode
    for (auto ite = m_opCurrentUIEditModes.begin(); ite != m_opCurrentUIEditModes.end(); /**/)
    {
        if ((*ite) && (*ite)->GetUIDocID() == pUIDoc->GetId())
        {
            (*ite)->UpdateRibbonContextualPage();
            return true;
        }
        else
        {
            ++ite;
        }
    }

    return false;
}

IUiEditModeEvent* UiEditModeManager::GetUiEditModeEvent()
{
    return UiEventManager::GetInstance()->GetUiEditModeEvent();
}

IUiEditModeBehavior* UiEditModeManager::GetUiEditModeBehavior(IUiDocument* pUIDoc)
{
    for (auto ite = m_opCurrentUIEditModes.begin(); ite != m_opCurrentUIEditModes.end(); ++ite)
    {
        if (((*ite) != nullptr) && ((*ite)->GetUIDocID() == pUIDoc->GetId()))
        {
            return (*ite)->GetUiEditModeBehavior();
        }
    }
    return nullptr;
}

void UiEditModeManager::ClearUiEditModes()
{
    FOR_EACH_INDEX(idx, m_opCurrentUIEditModes)
    {
        if (m_opCurrentUIEditModes[idx] != nullptr)
        {
            m_opCurrentUIEditModes[idx]->OnBeforeExitEditMode();
        }
    }
    m_opCurrentUIEditModes.clear();
}


bool UiEditModeManager::SyncUiEditMode(IUiDocument* pUIDoc)
{
    // 找到当前UIDoc的当前UIEditMode
    if (!pUIDoc)
    {
        return false;
    }
    int curUIEditModeIdx = -1;
    FOR_EACH_INDEX(idx, m_opCurrentUIEditModes)
    {
        if (m_opCurrentUIEditModes[idx] && (m_opCurrentUIEditModes[idx]->GetUIDocID() == pUIDoc->GetId()))
        {
            curUIEditModeIdx = idx;
            break;
        }
    }

    // 找到当前Doc的当前EditModeUE
    IDocument* pDoc = pUIDoc->GetDbDocument();
    if (!pDoc)
    {
        return false;
    }
    IEditMode* pTopActiveEditMode = IEditMode::GetTopActiveEditMode(pDoc);

    // 避免重入
    if (m_isSyncingUIEditMode)
    {
        return false;
    }
    m_isSyncingUIEditMode = true;

    bool bUIEditModeChanged = false;
    // 同步UIEditMode和EditModeUE
    if (curUIEditModeIdx != -1 && pTopActiveEditMode)
    {
        GBMP_ASSERT(m_opCurrentUIEditModes[curUIEditModeIdx]->GetDocument() == pDoc);
        if (m_opCurrentUIEditModes[curUIEditModeIdx]->GetEditModeType() != pTopActiveEditMode->GetEditModeType())
        {
            // 不一致。先退出当前UIEditMode，再根据EditModeUE生成对应的UIEditMode
            m_opCurrentUIEditModes[curUIEditModeIdx]->OnBeforeExitEditMode();
            gcmp::OwnerPtr<IUiEditMode> opNewUIEditMode = IUiEditMode::CreateUIEditMode(pDoc, pUIDoc->GetId(), pTopActiveEditMode->GetEditModeType());
            m_opCurrentUIEditModes[curUIEditModeIdx] = TransferOwnership(opNewUIEditMode);
            m_opCurrentUIEditModes[curUIEditModeIdx]->UpdateRibbonContextualPage();

            bUIEditModeChanged = true;
        }
    }
    else if (curUIEditModeIdx != -1 && !pTopActiveEditMode)
    {
        // EditModeUE不存在，退出当前UIEditMode
        m_opCurrentUIEditModes[curUIEditModeIdx]->OnBeforeExitEditMode();
        m_opCurrentUIEditModes[curUIEditModeIdx] = nullptr;
        m_opCurrentUIEditModes.erase(m_opCurrentUIEditModes.begin() + curUIEditModeIdx);
        bUIEditModeChanged = true;
    }
    else if (curUIEditModeIdx == -1 && pTopActiveEditMode)
    {
        FOR_EACH_INDEX(i, m_opCurrentUIEditModes)
        {
            if (m_opCurrentUIEditModes[i] != nullptr)
            {
                m_opCurrentUIEditModes[i]->OnBeforeExitEditMode();
                m_opCurrentUIEditModes[i] = nullptr;
            }
            m_opCurrentUIEditModes.erase(m_opCurrentUIEditModes.begin() + i);
            i--;
        }

        // 根据EditModeUE生成对应的UIEditMode
        gcmp::OwnerPtr<IUiEditMode> opNewUIEditMode = IUiEditMode::CreateUIEditMode(pDoc, pUIDoc->GetId(), pTopActiveEditMode->GetEditModeType());
        m_opCurrentUIEditModes.push_back(TransferOwnership(opNewUIEditMode));
        m_opCurrentUIEditModes.back()->UpdateRibbonContextualPage();

        bUIEditModeChanged = true;
    }
    else
    {
        // neither UIEditMode nor EditModeUE exists, do nothing
    }

    if (bUIEditModeChanged)
    {
        UiEditModeEvent* pUiEditModeEvent = dynamic_cast<UiEditModeEvent*>(UiEventManager::GetInstance()->GetUiEditModeEvent());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pUiEditModeEvent, L"同步编辑模式时获取编辑模式事件对象失败。",L"GDMPLab",L"2024-03-30");
        if (pUiEditModeEvent)
        {
            UiEditModeEventArgs uiEventArgs(UiEditModeEventType::UiEditModeChanged);
            pUiEditModeEvent->Emit(&uiEventArgs);
        }
    }

    m_isSyncingUIEditMode = false;

    return bUIEditModeChanged;
}
